using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ControladorDifuso;

namespace GuiDifuso
{
    public partial class VentanaPrincipal : Form
    {
        ControladorDifuso.Conjunto.FabricaConjuntos fabricaConjuntos;
        ControladorDifuso.Complementos.FabricaComplementadores fabricaComplementos;
        ControladorDifuso.Implicaciones.FabricaImplicaciones fabricaImplicaciones;
        ControladorDifuso.Conjunto.EspacioDifuso consecuente;
        ControladorDifuso.Defusificadores.FabricaDefusificadores fabricaDefusificadores;
        ParametrizarNorma parametrizadorNorma;
        EstablercerEntradas ingresoEntradas;
        

        public VentanaPrincipal()
        {
            InitializeComponent();
            this.fabricaConjuntos = new ControladorDifuso.Conjunto.FabricaConjuntos();
            this.fabricaImplicaciones = new ControladorDifuso.Implicaciones.FabricaImplicaciones();
            this.fabricaComplementos = new ControladorDifuso.Complementos.FabricaComplementadores();
            this.fabricaDefusificadores = new ControladorDifuso.Defusificadores.FabricaDefusificadores();
            this.parametrizadorNorma = new ParametrizarNorma();
            this.ingresoEntradas = new EstablercerEntradas();
        }

        private void VentanaPrincipal_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }

        private void btParametrizarNorma_Click(object sender, EventArgs e)
        {
            this.parametrizadorNorma.ShowDialog();
            if (this.parametrizadorNorma.DialogResult == DialogResult.OK)
            {
                this.lbxNormas.Items.Add(this.parametrizadorNorma.Descripcion);
            }
        }

        private void btEstablecerEntrada_Click(object sender, EventArgs e)
        {
            if (this.lbxAntecedentes.SelectedItem != null)
            {
                this.ingresoEntradas.Antecedente = (ControladorDifuso.Conjunto.EspacioDifuso)this.lbxAntecedentes.SelectedItem;
                this.ingresoEntradas.ShowDialog();
            }
            else
            {
               MessageBox.Show("Seleccione un antecedente para establecer la entrada", "No se puede eliminar espacio", MessageBoxButtons.OK, MessageBoxIcon.Error);
               return;
            }
            this.adssPlotConsecuente.Clear();
            this.adssPlotConsecuente.endX = (double)this.consecuente.ValorMaximo;
            this.adssPlotConsecuente.startX = (double)this.consecuente.ValorMinimo;
            this.adssPlotConsecuente.title = this.consecuente.Descripcion;
            this.adssPlotConsecuente.stepX = (this.adssPlotConsecuente.endX - this.adssPlotConsecuente.startX) / 10;
            double anchoPluma = (0.1 / (this.adssPlotConsecuente.endX - this.adssPlotConsecuente.startX));
            foreach (ControladorDifuso.Conjunto.ConjuntoDifuso conjunto in this.consecuente.ConjuntosDifusos)
            {
                double[] xPuntos, yPuntos;
                xPuntos = new double[ControladorDifuso.Conjunto.EspacioDifuso.NumeroMuestras];
                yPuntos = new double[ControladorDifuso.Conjunto.EspacioDifuso.NumeroMuestras];
                conjunto.Muestreo(ref xPuntos, ref yPuntos);
                this.adssPlotConsecuente.Plot(xPuntos, yPuntos, Color.Blue, anchoPluma);
            }
        }

        private void btRemoverEspacioDifuso_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.lbxEspaciosDifusos.SelectedItem == this.consecuente)
                {
                    MessageBox.Show("No se puede eliminar el espacio consecuente", "No se puede eliminar espacio", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                this.lbxEspaciosDifusos.Items.Remove(this.lbxEspaciosDifusos.SelectedItem);
            }
            catch
            {
            }
        }

        private void btRemoverConjunto_Click(object sender, EventArgs e)
        {
            try
            {
                ((ControladorDifuso.Conjunto.EspacioDifuso)this.lbxEspaciosDifusos.SelectedItem).ConjuntosDifusos.Remove(this.lbxConjuntos.SelectedItem);
                this.lbxConjuntos.Items.Remove(this.lbxConjuntos.SelectedItem);
                this.lbxEspaciosDifusos_SelectedIndexChanged(sender, e);
            }
            catch
            {
            }
        }

        private void btRemoverRegla_Click(object sender, EventArgs e)
        {
            try
            {
                this.lbxReglas.Items.Remove(this.lbxReglas.SelectedItem);
            }
            catch
            {
            }
        }

        private void VentanaPrincipal_Load(object sender, EventArgs e)
        {
            this.cbConjuntos.Items.AddRange(this.fabricaConjuntos.Lista);
            this.cbConjuntos.SelectedIndex = 0;
            this.lbxComplementos.Items.AddRange(this.fabricaComplementos.Lista);
            this.lbxComplementos.SelectedIndex = 0;
            this.lbxImplicaciones.Items.AddRange(this.fabricaImplicaciones.Lista);
            this.lbxImplicaciones.SelectedIndex = 0;
            this.lbxDefusificadores.Items.AddRange(this.fabricaDefusificadores.Lista);
            this.lbxDefusificadores.SelectedIndex = 0;
        }

        private void btAgregarEspacioDifuso_Click(object sender, EventArgs e)
        {
            if (this.tbDescripcionEspacioDifuso.Text == string.Empty)
            {
                MessageBox.Show( "Ingrese una descripcion del espacio difuso","Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            ControladorDifuso.Conjunto.EspacioDifuso espacio = new ControladorDifuso.Conjunto.EspacioDifuso(this.tbDescripcionEspacioDifuso.Text, this.nuValorMinimoEspacioDifuso.Value, this.nUValorMaximoExpacioDifuso.Value);
            this.lbxEspaciosDifusos.Items.Add(espacio);
            if (this.cbEsConsecuente.Checked)
            {
                if (MessageBox.Show( "Ha seleccionado este conjunto como unico consecuente, desea continuar?","Seleccion del unico consecuente", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
                {
                    this.consecuente = espacio;
                    this.cbEsConsecuente.Enabled = false;
                    this.cbEsConsecuente.Checked = false;
                }
            }
        }

        private void lbxEspaciosDifusos_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                this.adssDefinicion.Clear();
                this.adssDefinicion.endX = (double)(((ControladorDifuso.Conjunto.EspacioDifuso)lbxEspaciosDifusos.SelectedItem).ValorMaximo);
                this.adssDefinicion.startX = (double)(((ControladorDifuso.Conjunto.EspacioDifuso)lbxEspaciosDifusos.SelectedItem).ValorMinimo);
                this.adssDefinicion.title = ((ControladorDifuso.Conjunto.EspacioDifuso)lbxEspaciosDifusos.SelectedItem).Descripcion;
                this.adssDefinicion.stepX = (this.adssDefinicion.endX - this.adssDefinicion.startX)/10;
                double anchoPluma = (0.1 / (this.adssDefinicion.endX - this.adssDefinicion.startX));
                this.lbxConjuntos.Items.Clear();
                this.lbxConjuntos.Items.AddRange(((ControladorDifuso.Conjunto.EspacioDifuso)lbxEspaciosDifusos.SelectedItem).ConjuntosDifusos.ToArray());
                foreach (ControladorDifuso.Conjunto.ConjuntoDifuso conjunto in this.lbxConjuntos.Items)
                {
                    double[] xPuntos, yPuntos;
                    xPuntos = new double[ControladorDifuso.Conjunto.EspacioDifuso.NumeroMuestras];
                    yPuntos = new double[ControladorDifuso.Conjunto.EspacioDifuso.NumeroMuestras];
                    conjunto.Muestreo(ref xPuntos, ref yPuntos);
                    this.adssDefinicion.Plot(xPuntos, yPuntos, Color.Blue, anchoPluma);
                }
            }
            catch
            {
            }
        }

        private void btAgregarConjunto_Click(object sender, EventArgs e)
        {
            if (this.tbDescripcionConjuntosDifusos.Text == string.Empty)
            {
                MessageBox.Show("Ingrese una descripcion del conjunto", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (this.lbxEspaciosDifusos.SelectedItem == null)
            {
                MessageBox.Show("Seleccione un Espacio Difuso", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            ControladorDifuso.Conjunto.ConjuntoDifuso conjunto;
            try
            {
                conjunto = this.fabricaConjuntos.FabricarConjunto(this.cbConjuntos.SelectedItem.ToString(), this.tbDescripcionConjuntosDifusos.Text, this.nUParametroAlfa.Value, this.nUParamatroBeta.Value, this.nUParametroGama.Value, this.nUParamatroDelta.Value);
                ((ControladorDifuso.Conjunto.EspacioDifuso)this.lbxEspaciosDifusos.SelectedItem).AgregarConjunto(conjunto);
                this.lbxConjuntos.Items.Add(conjunto);
                this.lbxEspaciosDifusos_SelectedIndexChanged(sender, e);
            }
            catch
            {
            }
        }

        private void tabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.tabControl.SelectedIndex == 0)
                return;
            if (this.lbxEspaciosDifusos.Items.Count <2)
            {
                MessageBox.Show("Cree al menos 2 espacios difusos antes de continuar", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.tabControl.SelectedIndex = 0;
                return;
            }
            
            if (this.consecuente == null)
            {
                MessageBox.Show("Ingrese un espacio difuso como consecuente", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.tabControl.SelectedIndex = 0;
                return;
            }
            if (this.tabControl.SelectedIndex == 1)
            {
                this.lbxConsecuentes.Items.Clear();
                foreach (ControladorDifuso.Conjunto.EspacioDifuso espacio in this.lbxEspaciosDifusos.Items)
                {
                    if (espacio == this.consecuente)
                        this.lbxConsecuentes.Items.AddRange(espacio.ConjuntosDifusos.ToArray());
                    else
                        foreach (ControladorDifuso.Conjunto.ConjuntoDifuso conjunto in espacio.ConjuntosDifusos)
                        {
                            if (!this.lbxRelaciones.Items.Contains(conjunto))
                            {
                                this.lbxRelaciones.Items.Add(conjunto);
                                this.lbxRelacionesImplicaciones.Items.Add(conjunto);
                            }
                        }
                }
            }

            if (this.tabControl.SelectedIndex == 2)
            {
                this.lbxAntecedentes.Items.Clear();
                foreach (object espacio in this.lbxEspaciosDifusos.Items)
                {
                    if (espacio != this.consecuente)
                        this.lbxAntecedentes.Items.Add(espacio);
                }
            }
        }

        private void btImportarElemento_Click(object sender, EventArgs e)
        {
            if(this.lbxNormasRelacionar.Items.Count < 2 && this.lbxRelaciones.SelectedItem !=null)
                this.lbxNormasRelacionar.Items.Add(this.lbxRelaciones.SelectedItem);
        }

        private void btQuitarElementoRelacionar_Click(object sender, EventArgs e)
        {
            this.lbxNormasRelacionar.Items.Remove(this.lbxNormasRelacionar.SelectedItem);
        }

        private void btCrearRelacion_Click(object sender, EventArgs e)
        {
            if (this.lbxNormasRelacionar.Items.Count != 2)
            {
                MessageBox.Show("Traiga 2 elementos para relacionar", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (this.lbxNormas.SelectedItem == null)
            {
                MessageBox.Show("Seleccione una norma para la relacion", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            ControladorDifuso.Implicaciones.Relacion relacion = new ControladorDifuso.Implicaciones.Relacion((ControladorDifuso.Conjunto.IPertenencia)this.lbxNormasRelacionar.Items[0], (ControladorDifuso.Conjunto.IPertenencia)this.lbxNormasRelacionar.Items[1]);
            relacion.Norma = this.parametrizadorNorma.obtenerDeHistorial(this.lbxNormas.SelectedIndex);
            this.lbxRelaciones.Items.Add(relacion);
            this.lbxRelacionesImplicaciones.Items.Add(relacion);
            this.lbxNormasRelacionar.Items.Clear();
        }

        private void btCrearComplemento_Click(object sender, EventArgs e)
        {
            if (this.lbxRelaciones.SelectedItem == null)
            {
                MessageBox.Show("Seleccione una norma para complementarla", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (this.lbxComplementos.SelectedItem == null)
            {
                MessageBox.Show("Seleccione un tipo de complemento", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            ControladorDifuso.Complementos.Complemento complemento = this.fabricaComplementos.FabricarComplemento(this.lbxComplementos.SelectedItem.ToString(),(ControladorDifuso.Conjunto.IPertenencia) this.lbxRelaciones.SelectedItem);
            this.lbxRelaciones.Items.Add(complemento);
            this.lbxRelacionesImplicaciones.Items.Add(complemento);
        }

        private void btAgregarRegla_Click(object sender, EventArgs e)
        {
            if (this.lbxRelacionesImplicaciones.SelectedItem == null)
            {
                MessageBox.Show("Seleccione una relacion o conjunto para la regla", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (this.lbxImplicaciones.SelectedItem == null)
            {
                MessageBox.Show("Seleccione una implicacion", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (this.lbxComplementos.SelectedItem == null)
            {
                MessageBox.Show("Seleccione un consecuente para la regla", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            ControladorDifuso.Implicaciones.Implicacion implicacion;
            implicacion = this.fabricaImplicaciones.FabricarImplicacion(this.lbxImplicaciones.SelectedItem.ToString(), (ControladorDifuso.Conjunto.IPertenencia)this.lbxRelacionesImplicaciones.SelectedItem, (ControladorDifuso.Conjunto.ConjuntoDifuso)this.lbxConsecuentes.SelectedItem);
            this.lbxReglas.Items.Add(implicacion);

        }

        private void btDefusificar_Click(object sender, EventArgs e)
        {
            if (this.lbxDefusificadores.SelectedItem == null)
            {
                MessageBox.Show("Seleccione un defusificador ", "Falta ingresar campos", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            ControladorDifuso.Defusificadores.Defusificador defusificador;
            defusificador = this.fabricaDefusificadores.FabricarDefusificador(this.lbxDefusificadores.SelectedItem.ToString());
            defusificador.EspacioConsecuente = this.consecuente;
            foreach (object regla in this.lbxReglas.Items)
            {
                defusificador.Implicaciones.Add(regla);
            }
            this.tbDefusificado.Text = defusificador.Defusificar().ToString();
            double[] xPuntosH, yPuntosH;
            xPuntosH = new double[ControladorDifuso.Conjunto.EspacioDifuso.NumeroMuestras];
            yPuntosH = new double[ControladorDifuso.Conjunto.EspacioDifuso.NumeroMuestras];
            defusificador.Muestreo(ref xPuntosH, ref yPuntosH);
            double anchoPluma = (0.1 / (this.adssPlotConsecuente.endX - this.adssPlotConsecuente.startX));
            this.adssPlotConsecuente.Hist(xPuntosH, yPuntosH, anchoPluma, Color.Cyan);
        }
    }
}